/**
 * 标记点封装类
 * 基于 OpenLayers Overlay 实现的标记点
 */

import { Overlay } from 'ol';
import { Map as OlMap } from 'ol';
import { Coordinate } from '../types';
import { DataUtil } from '../utils/data';
import { StyleUtil } from '../utils/style';
import { EventEmitter } from '../utils/event';

/**
 * 标记点配置选项
 */
export interface MarkerOptions {
  /** 标记点ID */
  id?: string;
  /** 坐标 */
  coordinate: Coordinate;
  /** 图标URL或SVG字符串 */
  icon?: string;
  /** 图标大小 */
  iconSize?: [number, number];
  /** 图标锚点 [x, y] (0-1) */
  anchor?: [number, number];
  /** 是否可拖拽 */
  draggable?: boolean;
  /** 是否自动定位 */
  autoPan?: boolean;
  /** 标记点标题（鼠标悬停显示） */
  title?: string;
  /** 标记点类名 */
  className?: string;
  /** 点击事件回调 */
  onClick?: (marker: Marker) => void;
  /** 拖拽开始回调 */
  onDragStart?: (marker: Marker) => void;
  /** 拖拽中回调 */
  onDrag?: (marker: Marker, coordinate: Coordinate) => void;
  /** 拖拽结束回调 */
  onDragEnd?: (marker: Marker, coordinate: Coordinate) => void;
}

/**
 * 标记点类
 */
export class Marker extends EventEmitter {
  /** OpenLayers Overlay 实例 */
  private overlay: Overlay | null = null;
  /** 标记点容器元素 */
  private element: HTMLElement | null = null;
  /** 标记点配置 */
  private options: MarkerOptions;
  /** 当前坐标 */
  private currentCoordinate: Coordinate;
  /** 是否正在拖拽 */
  private isDragging: boolean = false;
  /** 拖拽开始位置 */
  private dragStartPosition: [number, number] | null = null;

  /**
   * 构造函数
   * @param options 标记点配置
   */
  constructor(options: MarkerOptions) {
    super();
    this.options = {
      iconSize: [32, 32],
      anchor: [0.5, 1],
      draggable: false,
      autoPan: false,
      className: 'zss-ol-marker',
      ...options
    };
    this.currentCoordinate = options.coordinate;
    this.createElement();
  }

  /**
   * 创建标记点元素
   */
  private createElement(): void {
    this.element = document.createElement('div');
    this.element.className = this.options.className || 'zss-ol-marker';
    this.element.style.cssText = `
      position: absolute;
      cursor: ${this.options.draggable ? 'move' : 'pointer'};
      user-select: none;
    `;

    if (this.options.title) {
      this.element.title = this.options.title;
    }

    // 创建图标
    const icon = document.createElement('img');
    if (this.options.icon) {
      icon.src = this.options.icon;
    } else {
      // 默认图标（SVG）
      icon.src = 'data:image/svg+xml;base64,' + btoa(`
        <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
          <path d="M16 2 C10 2 5 7 5 13 C5 20 16 30 16 30 C16 30 27 20 27 13 C27 7 22 2 16 2 Z" 
                fill="#FF0000" stroke="#fff" stroke-width="2"/>
          <circle cx="16" cy="13" r="5" fill="#fff"/>
        </svg>
      `);
    }
    icon.style.cssText = `
      width: ${this.options.iconSize![0]}px;
      height: ${this.options.iconSize![1]}px;
      display: block;
      pointer-events: none;
    `;
    this.element.appendChild(icon);

    // 设置锚点
    const [anchorX, anchorY] = this.options.anchor!;
    this.element.style.transform = `translate(-${anchorX * 100}%, -${anchorY * 100}%)`;

    // 添加拖拽功能
    if (this.options.draggable) {
      this.setupDrag();
    }

    // 添加点击事件
    this.element.addEventListener('click', (e) => {
      e.stopPropagation();
      if (this.options.onClick) {
        this.options.onClick(this);
      }
      this.emit('click', this);
    });

    // 创建 Overlay
    this.overlay = new Overlay({
      element: this.element,
      positioning: 'center-center',
      autoPan: this.options.autoPan ? {
        animation: { duration: 250 },
        margin: 20
      } : false
    });
  }

  /**
   * 设置拖拽功能
   */
  private setupDrag(): void {
    if (!this.element) return;

    let map: OlMap | null = null;

    const onMouseDown = (e: MouseEvent) => {
      e.preventDefault();
      e.stopPropagation();
      
      if (!this.overlay) return;
      map = this.overlay.getMap();
      if (!map) return;

      this.isDragging = true;
      this.dragStartPosition = [e.clientX, e.clientY];
      
      if (this.options.onDragStart) {
        this.options.onDragStart(this);
      }
      this.emit('dragstart', this);

      const onMouseMove = (e: MouseEvent) => {
        if (!this.isDragging || !map || !this.overlay) return;

        const pixel = map.getEventPixel(e);
        const coordinate = map.getCoordinateFromPixel(pixel);
        if (coordinate) {
          const lonLat = DataUtil.fromOlCoordinate(coordinate as [number, number]);
          this.setPosition(lonLat);

          if (this.options.onDrag) {
            this.options.onDrag(this, lonLat);
          }
          this.emit('drag', this, lonLat);
        }
      };

      const onMouseUp = () => {
        if (!this.isDragging) return;

        this.isDragging = false;
        this.dragStartPosition = null;

        if (this.options.onDragEnd) {
          this.options.onDragEnd(this, this.currentCoordinate);
        }
        this.emit('dragend', this, this.currentCoordinate);

        document.removeEventListener('mousemove', onMouseMove);
        document.removeEventListener('mouseup', onMouseUp);
      };

      document.addEventListener('mousemove', onMouseMove);
      document.addEventListener('mouseup', onMouseUp);
    };

    this.element.addEventListener('mousedown', onMouseDown);
  }

  /**
   * 设置位置
   * @param coordinate 坐标
   */
  setPosition(coordinate: Coordinate): void {
    if (!this.overlay) return;

    this.currentCoordinate = coordinate;
    const olCoord = DataUtil.toOlCoordinate(coordinate);
    this.overlay.setPosition(olCoord);
    this.emit('positionchange', coordinate);
  }

  /**
   * 获取位置
   * @returns 当前坐标
   */
  getPosition(): Coordinate {
    return this.currentCoordinate;
  }

  /**
   * 设置图标
   * @param iconUrl 图标URL
   */
  setIcon(iconUrl: string): void {
    if (!this.element) return;

    const img = this.element.querySelector('img');
    if (img) {
      img.src = iconUrl;
      this.options.icon = iconUrl;
      this.emit('iconchange', iconUrl);
    }
  }

  /**
   * 设置是否可拖拽
   * @param draggable 是否可拖拽
   */
  setDraggable(draggable: boolean): void {
    this.options.draggable = draggable;
    if (this.element) {
      this.element.style.cursor = draggable ? 'move' : 'pointer';
      if (draggable) {
        this.setupDrag();
      }
    }
  }

  /**
   * 添加到地图
   * @param map 地图实例
   */
  addTo(map: OlMap): void {
    if (!this.overlay) return;

    const olCoord = DataUtil.toOlCoordinate(this.currentCoordinate);
    this.overlay.setPosition(olCoord);
    map.addOverlay(this.overlay);
    this.emit('add', map);
  }

  /**
   * 从地图移除
   */
  remove(): void {
    if (!this.overlay) return;

    const map = this.overlay.getMap();
    if (map) {
      map.removeOverlay(this.overlay);
    }
    this.emit('remove');
  }

  /**
   * 获取 OpenLayers Overlay 实例
   * @returns Overlay 实例
   */
  getOverlay(): Overlay | null {
    return this.overlay;
  }

  /**
   * 获取标记点ID
   * @returns 标记点ID
   */
  getId(): string | undefined {
    return this.options.id;
  }

  /**
   * 销毁标记点
   */
  destroy(): void {
    this.remove();
    if (this.element) {
      this.element.remove();
      this.element = null;
    }
    this.overlay = null;
    this.removeAllListeners();
    this.emit('destroy');
  }
}

